/**
 * @file main.cpp
 * @author Christian
 *
 * XMLCC is distributed under the MIT License (MIT); this file is part of.
 *
 * Copyright (c) 2008-2022 Christian (graetz23@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef __cplusplus
#error use a C++ compiler for XMLCC::
#endif

/******************************************************************************/

#include "./xmlcc/xmlcc.h" // include of XMLCC::

/******************************************************************************/

// XMLCC:: is still keeping DOM::, SAX::, CFG::, SYS::, and TEST::
using namespace XMLCC;

/******************************************************************************/

int // main
main( int argc, char** argv ) {

  /****************************************************************************/

  try { // try everything ~8>

    /**************************************************************************/

    if( true ) { // print version and built date at start up

      std::cout << "XMLCC:: version " << _XMLCC_VERSION_ << " package "
          << _XMLCC_PACKAGE_ << std::endl << std::flush;
      std::cout << "XMLCC:: built " << _XMLCC_BUILD_DATE_ << " "
          << _XMLCC_BUILD_TIME_ << std::endl << std::flush;
      std::cout << std::endl << std::flush;

    } // if

    /**************************************************************************/

    if( true ) { // generating the actual config file for XMLCC

      std::cout << "checking config file .. " << std::flush;
      CFG::Config config;
      if( config.exists( ) ) {
        std::cout << "exists!" << std::endl << std::endl << std::flush;
      } else {
        std::cout << "not existing; going to generating one .. " << std::flush;
        config.write( config.generate( ) );
        std::cout << "done!" << std::endl << std::endl << std::flush;
      } // if

    } // if

    /**************************************************************************/

#ifdef _XMLCC_USE_TEST_ // see xmlccTest.h & xmlccTest.cpp
    XMLCC::TEST::run( ); // run unit tests of XMLCC as set in config file
#endif // _XMLCC_USE_TEST_

    /**************************************************************************/

    if( true ) { // generating a simple web page by using DOM objects directly

      // example how to generate, view, and write content in XML (HTML)
      std::cout << "generating DOM tree .. " << std::flush;
      DOM::Root* xml = 0;
      xml = new DOM::Root( "xmlcc.html", new DOM::Doctype( ),
        new DOM::Comment( "XMLCC 1.01 20200307 Amara Faith" ),
        new DOM::Element( "html",
          new DOM::Element( "head",
            new DOM::Element( "title",
              new DOM::Value( "HTML generated by XMLCC" ) ) ),
          new DOM::Element( "body" ),
          new DOM::Element( "center",
            new DOM::Comment( "HTML was generated by XMLCC" ),
            new DOM::Value( "Hello" ),
            new DOM::Element( "b", new DOM::Value( "WWW" ) ),
            new DOM::Value( "from XMLCC" ), new DOM::Element( "br" ),
            new DOM::Element( "a",
              new DOM::Attribute( "href",
                "https://github.com/graetz23/xmlcc/" ),
              new DOM::Value( "visit project page" ) ) ) ) );
      std::cout << "done!" << std::endl << std::flush;

//      std::cout << std::endl << std::flush;
//      std::cout << "showing DOM tree to file .. " << std::endl << std::flush;
//      std::cout << xml << std::endl << std::flush; // DOM:: 2 std::cout
//      std::cout << "done!" << std::endl << std::flush;

      std::cout << "writing DOM tree to file .. " << std::flush;
      std::fstream file; // open file
      file.open( ( (char*)( xml->getStr( ).c_str( ) ) ), std::ios::out );
      file << xml; // DOM tree 2 std::ostream
      file.close( );
      delete xml; // deletes complete DOM tree
      std::cout << "done!" << std::endl << std::endl << std::flush;

    } // if

    /**************************************************************************/

    if( true ) { // generating a simple web page by using DOM objects directly

      // TODO implement web page example using DOM::Controller

    } // if

    /**************************************************************************/

    XMLCC::Str fileName = ""; // file name by console or use xmlccMalformed.xml
    if( argc >= 2 )
      fileName.append( argv[ 1 ] );
    else
      fileName = "xmlccMalformed.xml";

    /**************************************************************************/

    if( true ) { // parsing to document object model (DOM)

      std::cout << "parsing to document object model (DOM): " << fileName
          << std::endl << std::flush;
      XMLCC::DOM::Core core; // methods for parsing 2 DOM tree
      XMLCC::DOM::Root* root = core.parseFile2DomTree( fileName ); // DOM tree
      if( root != 0 ) {
        std::cout << root << std::flush << std::endl; // DOM tree 2 std::ostream
        delete root; // deletes complete DOM tree
      } // if root

    } // if

    /**************************************************************************/

    if( true ) { // parsing using simple API for XML (SAX)

      std::cout << "parsing by simple API for XML (SAX): " << fileName
          << std::endl << std::flush;
      // SAX parser; parsing, cleaning, and calling SAX handler methods
      XMLCC::SAX::Parser* parser = new XMLCC::SAX::Parser(
        new XMLCC::SAX::HandlerExample( ) );
      parser->parseFile( fileName ); // HandlerExample is streaming to std::cout
      delete parser;

    } // if

    /**************************************************************************/

    // std::cout << "done!" << std::endl << std::flush;
    /**************************************************************************/

  } catch( XMLCC::SYS::Failure& f ) { // own exception class
    std::cout << "SYS::Failure caught:" << std::endl << std::flush;
    std::cout << f;
  } catch( XMLCC::SYS::Error& e ) { // own exception class
    std::cout << "SYS::Error caught:" << std::endl << std::flush;
    std::cout << e;
  } catch( XMLCC::SYS::Exception& e ) { // own exception class
    std::cout << "SYS::Exception caught:" << std::endl << std::flush;
    std::cout << e;
  } catch( std::exception& e ) { // standard exception class
    std::cout << "std::exception caught:" << std::endl << std::flush;
    std::cout << e.what( ) << std::endl << std::flush;
  } catch( ... ) { // any other exception thrown
    std::cout << "Strange exception caught:" << std::endl << std::flush;
    XMLCC::SYS::Exception e;
    e.nuke( ); // nuke screen
  } // try

  return 0;

} // main

/******************************************************************************/
